package com.yunquan.ohana.ui.photos.camera

import android.Manifest
import android.annotation.SuppressLint
import android.content.ContentValues
import android.content.Intent
import android.content.pm.PackageManager
import android.os.Bundle
import android.os.CountDownTimer
import android.provider.MediaStore
import androidx.camera.core.CameraSelector
import androidx.camera.core.ImageCapture
import androidx.camera.core.ImageCaptureException
import androidx.camera.lifecycle.ProcessCameraProvider
import androidx.camera.video.MediaStoreOutputOptions
import androidx.camera.video.Recorder
import androidx.camera.video.Recording
import androidx.camera.video.VideoCapture
import androidx.camera.video.VideoRecordEvent
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
import com.yunquan.ohana.BR
import com.yunquan.ohana.R
import com.yunquan.ohana.base.ui.BaseActivity
import com.yunquan.ohana.databinding.ActivityCameraBinding
import com.yunquan.ohana.dialog.TipDialog
import com.yunquan.ohana.utils.L
import com.yunquan.ohana.utils.SystemUtils
import com.yunquan.ohana.utils.ToastUtils
import java.text.SimpleDateFormat
import java.util.Locale
import java.util.concurrent.ExecutorService
import java.util.concurrent.Executors

class MyCameraActivity : BaseActivity<ActivityCameraBinding, MyCameraViewModel>() {

    private lateinit var imageCapture: ImageCapture
    private lateinit var videoCapture: VideoCapture<Recorder>
    private lateinit var cameraExecutor: ExecutorService
    private var isRecording = false
    private var recording: Recording? = null

    private var isPermission = false
    private var showDialog = false

    private var countDownTimer: CountDownTimer? = null


    override fun initContentView(savedInstanceState: Bundle?): Int {
        return R.layout.activity_camera
    }

    override fun initVariableId(): Int {
        return BR.cameraViewModel
    }

    @SuppressLint("ClickableViewAccessibility")
    override fun initData(savedInstanceState: Bundle?) {
        super.initData(savedInstanceState)
        // 获取需要的拍照类型
        val bundle = intent.extras
        bundle?.let {
            val type = it.getInt("type", 0)
            viewModel!!.showType.set(type)
        }
        // 处理权限
        if (allPermissionsGranted()) {
            startCamera()
        } else {
            ActivityCompat.requestPermissions(this, REQUIRED_PERMISSIONS, REQUEST_CODE_PERMISSIONS)
        }
        binding!!.btnPlay.setOnClickListener {
            if(viewModel!!.showType.get() == 1){
                takePhoto()
            }else if(viewModel!!.showType.get() == 2){
                if(isRecording){
                    stopRecording()
                }else{
                    startRecording()
                }
            }
        }
        cameraExecutor = Executors.newSingleThreadExecutor()
    }

    private fun startCamera() {
        val cameraProviderFuture = ProcessCameraProvider.getInstance(this)

        cameraProviderFuture.addListener({
            val cameraProvider: ProcessCameraProvider = cameraProviderFuture.get()
            val preview = androidx.camera.core.Preview.Builder().build().also {
                it.surfaceProvider = binding!!.pvCamera.surfaceProvider
            }

            imageCapture = ImageCapture.Builder().build()
            val recorder = Recorder.Builder().build()
            videoCapture = VideoCapture.withOutput(recorder)

            val cameraSelector = CameraSelector.DEFAULT_BACK_CAMERA

            try {
                cameraProvider.unbindAll()
                cameraProvider.bindToLifecycle(this, cameraSelector, preview, imageCapture, videoCapture)
            } catch (exc: Exception) {
                L.e("相机用例绑定失败")
                exc.printStackTrace()
            }

        }, ContextCompat.getMainExecutor(this))
    }

    private fun takePhoto() {
        val name = SimpleDateFormat("yyyyMMdd_HHmmss", Locale.getDefault()).format(System.currentTimeMillis())
        val contentValues = ContentValues().apply {
            put(MediaStore.MediaColumns.DISPLAY_NAME, "IMG_$name.jpg")
            put(MediaStore.MediaColumns.MIME_TYPE, "image/jpeg")
            put(MediaStore.Images.Media.RELATIVE_PATH, "DCIM/Camera")
        }

        val outputOptions = ImageCapture.OutputFileOptions.Builder(
            contentResolver,
            MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
            contentValues
        ).build()

        imageCapture.takePicture(
            outputOptions, ContextCompat.getMainExecutor(this), object : ImageCapture.OnImageSavedCallback {
                override fun onError(exc: ImageCaptureException) {
                    L.e("照片捕获失败: ${exc.message}")
                    exc.printStackTrace()
                }

                override fun onImageSaved(output: ImageCapture.OutputFileResults) {
                    val msg = "照片捕获成功: ${output.savedUri?.lastPathSegment}"
                    ToastUtils.showShort(msg)
                    L.d(msg)
                    if (output.savedUri?.lastPathSegment != null) {
//                        val data = PhotosUtils.instance.getImageByPath(output.savedUri?.lastPathSegment!!)
                        goBackResult(1,output.savedUri?.lastPathSegment!!)
                    }
                }
            })
    }

    private fun startRecording() {
        val name = SimpleDateFormat("yyyyMMdd_HHmmss", Locale.getDefault()).format(System.currentTimeMillis())
        val contentValues = ContentValues().apply {
            put(MediaStore.MediaColumns.DISPLAY_NAME, "VID_$name.mp4")
            put(MediaStore.MediaColumns.MIME_TYPE, "video/mp4")
            put(MediaStore.Video.Media.RELATIVE_PATH, "DCIM/Camera")
        }

        val outputOptions = MediaStoreOutputOptions.Builder(
            contentResolver,
            MediaStore.Video.Media.EXTERNAL_CONTENT_URI
        ).setContentValues(contentValues).build()

        recording = videoCapture.output
            .prepareRecording(this, outputOptions)
            .start(ContextCompat.getMainExecutor(this)) { recordEvent ->
                when (recordEvent) {
                    is VideoRecordEvent.Start -> {
                        isRecording = true
                        startCountdown()
                    }

                    is VideoRecordEvent.Finalize -> {
                        if (!recordEvent.hasError()) {
                            val uri = recordEvent.outputResults.outputUri
                            val msg = "视频捕获成功: ${uri.lastPathSegment}"
                            ToastUtils.showShort(msg)
                            L.d(msg)
                            if (uri.lastPathSegment != null) {
//                                val data = PhotosUtils.instance.getVideoByPath(uri.lastPathSegment!!)
                                goBackResult(2,uri.lastPathSegment!!)
                            }
                        } else {
                            L.e("视频捕获失败: ${recordEvent.error}")
                        }
                        isRecording = false
                    }
                }
            }
    }

    private fun stopRecording() {
        recording?.stop()
        recording = null
        countDownTimer?.cancel()
        countDownTimer = null
    }

    private fun startCountdown() {
        countDownTimer = object : CountDownTimer(MAX_VIDEO_DURATION, 1000) {
            override fun onTick(millisUntilFinished: Long) {
                val diff = MAX_VIDEO_DURATION - millisUntilFinished
                binding!!.pbProgress.progress = (diff / 1000).toInt()
            }

            override fun onFinish() {
                stopRecording()
            }
        }.start()
    }

    private fun allPermissionsGranted() = REQUIRED_PERMISSIONS.all {
        ContextCompat.checkSelfPermission(baseContext, it) == PackageManager.PERMISSION_GRANTED
    }

    override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<String>, grantResults: IntArray) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults)
        if (requestCode == REQUEST_CODE_PERMISSIONS) {
            if (allPermissionsGranted()) {
                isPermission = true
                startCamera()
            } else {
                isPermission = false
                showPermissionDialog()
            }
        }
    }

    override fun onResume() {
        super.onResume()
        if (!isPermission && !showDialog) {
            if (allPermissionsGranted()) {
                isPermission = true
                startCamera()
            } else {
                isPermission = false
                showPermissionDialog()
            }
        }
    }

    override fun onDestroy() {
        super.onDestroy()
        cameraExecutor.shutdown()
    }

    /**
     * 显示权限弹窗
     */
    private fun showPermissionDialog() {
        val dialog = TipDialog(this)
        dialog.setTitle(getString(R.string.not_permission))
        dialog.setMessage(getString(R.string.tip_not_permission_camera_and_record_audio))
        dialog.setRightBtn(getString(R.string.go_settings))
        dialog.setOnDialogClickListener(object : TipDialog.OnDialogClickListener() {
            override fun onRightClick() {
                super.onRightClick()
                SystemUtils.goToAppSettings(this@MyCameraActivity)
            }

            override fun onLeftClick() {
                super.onLeftClick()
                finish()
            }
        })
        dialog.setOnDismissListener {
            showDialog = false
        }
        dialog.show()
        showDialog = true
    }

    private fun goBackResult(type:Int,id:String) {
        val bundle = Bundle()
        bundle.putString("fileId", id)
        bundle.putInt("type", type)
        val intent = Intent()
        intent.putExtras(bundle)
        setResult(RESULT_CODE, intent)
        finish()
    }

    companion object {
        const val RESULT_CODE = 10001
        private const val REQUEST_CODE_PERMISSIONS = 10
        private val REQUIRED_PERMISSIONS = arrayOf(Manifest.permission.CAMERA, Manifest.permission.RECORD_AUDIO)
        private const val MAX_VIDEO_DURATION = 60000L
        private const val CLICK_DURATION = 500L
    }
}